package com.coincalf.service.impl;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.coincalf.api.aliyuncs.AliyunConfig;
import com.coincalf.api.aliyuncs.MailConfig;
import com.coincalf.entity.Sms;
import com.coincalf.framework.constants.Constant;
import com.coincalf.framework.enums.ResultCode;
import com.coincalf.framework.http.Response;
import com.coincalf.mapper.SmsMapper;
import com.coincalf.service.ConfigService;
import com.coincalf.service.SmsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.thymeleaf.spring5.SpringTemplateEngine;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 短信信息 服务实现类
 * </p>
 *
 * @author qiang
 * @since 2018-05-12
 */
@Service
@Slf4j
public class SmsServiceImpl extends ServiceImpl<SmsMapper, Sms> implements SmsService {


    @Autowired
    private ConfigService configService;
    @Autowired
    private AliyunConfig aliyunConfig;
    @Autowired
    private MailConfig mailConfig;
    @Autowired
    private SpringTemplateEngine springTemplateEngine;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /*@Override
    public void sendTo(Sms sms) {
        EntityWrapper<Config> ew = new EntityWrapper<>();
        ew.eq("type", "SMS");
        ew.eq("code", sms.getTemplateCode());
        Config config = configService.selectOne(ew);
        if (Optional.ofNullable(config).isPresent()) {
            if (!Strings.isNullOrEmpty(sms.getMobile())) {
                EntityWrapper<Config> signEntityWrapper = new EntityWrapper<>();
                signEntityWrapper.eq("type", "SMS");
                signEntityWrapper.eq("code", "SIGN");
                Config signConfig = configService.selectOne(signEntityWrapper);
                Map<String, Object> templateParam = sms.getTemplateParam();
                templateParam.put("sign", signConfig.getValue());
                String content = config.getValue();
                for (String s : templateParam.keySet()) {
                    content = content.replaceAll("\\$\\{".concat(s).concat("\\}")
                            , templateParam.get(s).toString());
                }
                sms.setContent(content);
                log.debug(sms.toString());
                SmsApi.sendTo(sms);
                sms.setStatus(1);
                super.insert(sms);
            } else if (!Strings.isNullOrEmpty(sms.getEmail())) {
                EntityWrapper<Config> signEntityWrapper = new EntityWrapper<>();
                signEntityWrapper.eq("type", "SMS");
                signEntityWrapper.eq("code", "SIGN");
                Config signConfig = configService.selectOne(signEntityWrapper);
                Map<String, Object> templateParam = sms.getTemplateParam();
                templateParam.put("sign", signConfig.getValue());
                String content = config.getValue();
                for (String s : templateParam.keySet()) {
                    content = content.replaceAll("\\$\\{".concat(s).concat("\\}")
                            , templateParam.get(s).toString());
                }
                sms.setContent(content);
                log.debug(sms.toString());

                // 如果是除杭州region外的其它region（如新加坡、澳洲Region），需要将下面的"cn-hangzhou"替换为"ap-southeast-1"、或"ap-southeast-2"。
                IClientProfile profile = aliyunConfig.getProfile();
                // 如果是除杭州region外的其它region（如新加坡region）， 需要做如下处理
                //try {
                //DefaultProfile.addEndpoint("dm.ap-southeast-1.aliyuncs.com", "ap-southeast-1", "Dm",  "dm.ap-southeast-1.aliyuncs.com");
                //} catch (ClientException e) {
                //e.printStackTrace();
                //}
                IAcsClient client = new DefaultAcsClient(profile);
                SingleSendMailRequest request = new SingleSendMailRequest();
                try {
                    //request.setVersion("2017-06-22");// 如果是除杭州region外的其它region（如新加坡region）,必须指定为2017-06-22
                    Map<String, Object> params = new HashMap<>();
                    params.put("sign", signConfig.getValue());
                    params.put("content", content);
                    Context context = new Context(LocaleContextHolder.getLocale());
                    context.setVariables(params);
                    String htmlBody = springTemplateEngine.process("mail", context);
                    request.setAccountName(mailConfig.getAccount());
                    request.setFromAlias(signConfig.getValue());
                    request.setAddressType(1);
                    request.setReplyToAddress(true);
                    request.setToAddress(sms.getEmail());
                    request.setSubject(config.getName());
                    request.setHtmlBody(htmlBody);
                    SingleSendMailResponse httpResponse = client.getAcsResponse(request);
                    System.out.println(httpResponse.getRequestId());
                    sms.setStatus(1);
                    sms.setRemark(httpResponse.getRequestId());
                } catch (ServerException e) {
                    e.printStackTrace();
                    sms.setRemark(e.getMessage());
                } catch (ClientException e) {
                    e.printStackTrace();
                    sms.setRemark(e.getMessage());
                } finally {
                    super.insert(sms);
                }
            }
        } else {
            throw new RuntimeException("短信模板不存在！");
        }
    }*/

    @Override
    public Response sendTo(Sms sms) {
        int i = SmsServiceImpl.randomNumber(6);
        sms.setContent("您的验证码为：" + i + "，请勿告诉其他人。有效期：3分钟！");
        String result = sendSms(sms.getMobile(), sms.getContent());
        int anInt = Integer.parseInt(result);
        if (anInt > 0) {
            String smsKey = Constant.SEND_SMS_KEY_PREFIX + sms.getMobile();
            redisTemplate.opsForValue().set(smsKey, String.valueOf(i), 3L, TimeUnit.MINUTES);
            log.info("{}短信发送成功: {}", sms.getMobile(), sms.getContent());
            return Response.ok();
        }
        return Response.err(Integer.parseInt(result), this.getInfo(anInt));
    }

    @Override
    public Response verifySms(Sms sms) {
        String smsKey = Constant.SEND_SMS_KEY_PREFIX + sms.getMobile();
        String value = redisTemplate.opsForValue().get(smsKey);
        if (StringUtils.isBlank(value))
            return Response.err(ResultCode.MOBILE_CODE_ERROR);
        if (value.equals(sms.getContent())) {
            redisTemplate.delete(smsKey);
            return Response.ok();
        }
        return Response.err(ResultCode.MOBILE_SMSCODE_ERROR);
    }

    @Override
    public void sendEmail(String email, String code) {
        //TODO 邮件发送

    }

    public static int randomNumber(int n) {
        int max = (int) (Math.pow(10, n) - (Math.pow(10, n - 1)) - 1);
        return (int) (new Random().nextInt(max) + (Math.pow(10, n - 1)));
    }


    /**
     * 短信发送失败原因
     *
     * @param code
     * @return
     */
    private String getInfo(int code) {
        switch (code) {
            case -1:
                return "没有该用户账户";
            case -2:
                return "接口密钥不正确";
            case -21:
                return "MD5接口密钥加密不正确";
            case -3:
                return "短信数量不足";
            case -11:
                return "该用户被禁用";
            case -14:
                return "短信内容出现非法字符";
            case -4:
                return "手机号格式不正确";
            case -41:
                return "手机号码为空";
            case -42:
                return "短信内容为空";
            case -51:
                return "短信签名格式不正确";
            case -52:
                return "短信签名太长";
            case -6:
                return "IP限制";
            default:
                return "未知异常";
        }
    }

    /**
     * 短信发送
     *
     * @param mobile  接收短信手机号
     * @param content 短信发送内容
     * @return 返回值 详见：http://www.smschinese.cn/api.shtml
     */
    public static String sendSms(String mobile, String content) {
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        try {
            //GET请求直接在链接后面拼上请求参数
            String smsUrl = "http://utf8.api.smschinese.cn/?Uid=AQPAQP&Key=d41d8cd98f00b204e980&smsMob=" + mobile + "&smsText=" + content;
            URL url = new URL(smsUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            //Get请求不需要DoOutPut
            conn.setDoOutput(false);
            conn.setDoInput(true);
            //设置连接超时时间和读取超时时间
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            //连接服务器
            conn.connect();
            // 取得输入流，并使用Reader读取
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
        } catch (Exception e) {
            log.error("短信发送失败 mobile={} e={}", mobile, e.getMessage());
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result.toString();
    }

}
